package com.sanmao.spring.demo.security.springsecurityoauth2demo.authentication.mobile;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;

import java.util.concurrent.TimeUnit;

/**
 * 手机认证提供类
 * @Author: Sanmao
 * @Date: 2021/08/31/12:25
 * @Description:
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MobileAuthenticationProvider implements AuthenticationProvider {

  private RedisTemplate<Object, Object> redisTemplate;

  private UserDetailsService userDetailsService;

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    MobileAuthenticationToken authenticationToken = (MobileAuthenticationToken) authentication;

    String mobile = authentication.getName();
    String smsCode = (String) authenticationToken.getCredentials();
    redisTemplate.opsForValue().set(mobile, smsCode, 10, TimeUnit.MINUTES);

    // TODO 切换redis
    String smsCodeFromRedis = "123456";
//    String smsCodeFromRedis = (String) redisTemplate.opsForValue().get(mobile);
    if(!smsCode.equals(smsCodeFromRedis)){
      throw new InternalAuthenticationServiceException("手机验证码不正确");
    }

    UserDetails user = userDetailsService.loadUserByUsername(mobile);
    if (user == null) {
      throw new InternalAuthenticationServiceException("无法获取用户信息");
    }

    MobileAuthenticationToken authenticationResult = new MobileAuthenticationToken(user,null, user.getAuthorities());
    authenticationResult.setDetails(authenticationToken.getDetails());
    return authenticationResult;
  }

  @Override
  public boolean supports(Class<?> authentication) {
    return MobileAuthenticationToken.class.isAssignableFrom(authentication);
  }
}
